#ifndef SCANCAMERADEVICE_H
#define SCANCAMERADEVICE_H

#include <QObject>
#include <QString>
#include <QMutex>
#include <QVariantMap>
#include <QAtomicInt>
#include <QtSerialPort/QSerialPort>
#include <QtSerialPort/QSerialPortInfo>
#include <QList>
#include <QByteArray>
#include <QTimer>
#include "CommandFrameBuilder.h"

// 命令执行结果枚举
enum class CommandResult {
    Success,          // 命令执行成功
    Failed,           // 命令执行失败
    Timeout,          // 命令超时
    InvalidParameter, // 参数无效
    NotConnected      // 设备未连接
};

/**
 * @brief 扫描相机设备类
 * @details 负责与扫描相机设备直接通信和控制，提供设备连接、参数设置和状态查询等功能
 */
class ScanCameraDevice : public QObject
{
    Q_OBJECT
public:
    /**
     * @brief 构造函数
     * @param portName 串口名称
     * @param parent 父对象指针（默认nullptr）
     */
    explicit ScanCameraDevice(const QString& portName, QObject *parent = nullptr);

    /**
     * @brief 析构函数
     */
    ~ScanCameraDevice() override;

    /**
     * @brief 打开设备连接
     * @return 连接成功返回true，失败返回false
     */
    bool open();

    /**
     * @brief 关闭设备连接
     */
    void close();

    /**
     * @brief 获取串口名称
     * @return 串口名称字符串
     */
    QString portName() const { return m_portName; }
    
    /**
     * @brief 搜索扫描相机设备
     * @return 找到的设备列表名称
     */
    static QList<QString> searchDevices();

    /**
     * @brief 检查设备是否已连接
     * @return 已连接返回true，否则返回false
     */
    bool isConnected() const { return m_isConnected; }

    /**
     * @brief 获取设备参数
     * @param paramName 参数名称
     * @return 参数值，若不存在或获取失败则返回无效QVariant
     */
    QVariant getParameter(const QString& paramName);

    /**
     * @brief 获取设备所有参数
     * @return 所有参数
     */
    QVariantMap getParameters();

    /**
     * @brief 设置设备所有参数
     * @return parameters 所有参数
     */
     void setParameters(QVariantMap parameters);

    /**
     * @brief 设置为聚焦模式(0x01)
     * @return 命令执行结果
     */
    CommandResult setFocusMode();
    
    /**
     * @brief 设置扫描模式(0x02)
     * @param mode 扫描模式：(0: 单次外触发, 1: 单次内触发, 2: 重频外触发 3: 重频内触发)
     * @return 命令执行结果
     */
    CommandResult setScanMode(uint8_t mode);

    /**
     * @brief 设置MCP门控状态(0x03)
     * @param mode 门控模式（1:门控开+外触发, 2:门控开, 3:门控关）
     * @param delayNs 延时时间（纳秒，范围0-2ms）
     * @param pulseWidthNs 脉宽时间（纳秒，范围0-2ms）
     * @return 命令执行结果
     */
    CommandResult setMCPGating(uint8_t mode, uint32_t delayNs, uint32_t pulseWidthNs);
    
    /**
     * @brief 设置阴极门控状态(0x04)
     * @param mode 门控模式（1:门控开+外触发, 2:门控开, 3:门控关）
     * @param delayNs 延时时间（纳秒，范围0-2ms）
     * @param pulseWidthNs 脉宽时间（纳秒，范围0-2ms）
     * @return 命令执行结果
     */
    CommandResult setCathodeGating(uint8_t mode, uint32_t delayNs, uint32_t pulseWidthNs);

    /**
     * @brief 设置MCP增益(0x05)
     * @param gain1 增益一值（0-800V）
     * @param gain2 增益二值（0-800V）
     * @return 命令执行结果
     */
    CommandResult setMCPGain(uint16_t gain1, uint16_t gain2);

    /**
     * @brief 设置档位位置(0x06)
     * @param gearPosition 档位位置值（bit7对应最高档）
     * @param componentSelection 组件选择（1:快组件, 2:中组件, 3:慢组件）
     * @return 命令执行结果
     */
    CommandResult setGearPosition(uint8_t gearPosition, uint8_t componentSelection);

    //TODO： 07(该指令不使用)

    /**
     * @brief 设置快门控制(0x08)
     * @param open true-打开，false-关闭
     * @return 命令执行结果
     */
    CommandResult setShutterControl(bool open);

    /**
     * @brief 设置20路TTL状态读取(0x09)
     * @return 命令执行结果
     */
    CommandResult setTTLStatusRead();

    /**
     * @brief 设置触发源选择(0x0B)
     * @param source 触发源 (0:由扫描触发线触发, 1:由门控触发接口触发)
     * @return 命令执行结果
     */
    CommandResult setTriggerSource(uint8_t source);

    /**
     * @brief 触发扫描(0x0C)
     * @return 命令执行结 c果
     */
    CommandResult triggerScan();
    
    /**
     * @brief 设置STPW寄存器配置(0x10 0x11 0x12)
     * @param componentType 组件类型（0:快组件, 1:中组件, 2:慢组件）
     * @param gearPositionValeu 当前设置的档位值
     * @return 命令执行结果
     */
    CommandResult setSTPWConfiguration(uint8_t componentType, QVector<uint16_t> gearPositionValeu);
    
    /**
     * @brief 设置内触发模式下延时参数(0x13)
     * @param delayNs 延时时间（纳秒，范围0-2ms）
     * @param pulseWidthNs 脉宽时间（纳秒，范围0-2ms）
     * @return 命令执行结果
     */
    CommandResult setInternalTriggerDelay(uint32_t delayNs, uint32_t pulseWidthNs);

    /**
     * @brief 设置外触发信号使能(0x14)
     * @param enable true-使能，false-禁用
     * @return 命令执行结果
     */
    CommandResult setExternalTriggerEnable(bool enable);
    
    /**
     * @brief  设置串口设备地址查询(0x50)
     * @return 命令执行结果
     */
    CommandResult setSerialDeviceSignalQuery();

    /**
     * @brief  设置监控信号查询(0x55)
     * @return 命令执行结果
     */
    CommandResult setMonitorSignalQuery();

private:

    /**
     * @brief 恢复默认设置
     * @return 命令执行结果
     */
    void resetToDefaults();

    /**
     * @brief 解析响应帧
     * @param frame 响应帧数据
     * @return 解析是否成功
     */
    bool parseResponseFrame(const QByteArray& frame);

    /**
     * @brief 执行原始命令
     * @param commandFrame 命令帧
     * @param commandCode 命令代码
     * @return 命令执行结果
     */
    CommandResult executeCommand(const QByteArray& commandFrame, unsigned char commandCode);

signals:
    /**
     * @brief Ad值变化信号
     * @param adValues ad变化后的值
     */
    void adValueChanged(const QVector<uint16_t>& adValues);

    /**
     * @brief gpio值变化信号
     * @param adValues ad变化后的值
     */
    void gpioStatusChanged(const QVector<bool>& gpioStatus);

    /**
     * @brief ttl状态变化信号
     * @param adValues ad变化后的值
     */
    void ttlStatuChanged(const QVector<bool>& ttlValues);

private:
    // 串口名称
    QString m_portName;
    
    // 串口对象
    QSerialPort* m_serialPort;
    
    // 设备连接状态
    QAtomicInt m_isConnected;
    
    // 线程安全锁
    mutable QMutex m_mutex;
    
    // 设备参数存储
    QVariantMap m_parameters;

    // 命令帧构建器
    static CommandFrameBuilder* m_CommandFrameBuilder;
      
    // 命令超时时间（毫秒）
    static const int COMMAND_TIMEOUT_MS = 100;

    //检索到的设备列表
    static QMap<QString,QSerialPortInfo> m_DeviceInfoMap;

};

#endif // SCANCAMERADEVICE_H
